package com.sjsu.cloudmanager.client.ui;

import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.Style;
import com.extjs.gxt.ui.client.data.BaseListLoadResult;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.*;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.CheckBoxSelectionModel;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.*;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sjsu.cloudmanager.client.CloudManager;
import com.sjsu.cloudmanager.client.LabManagerEvents;
import com.sjsu.cloudmanager.client.service.CloudLabServiceAsync;
import com.sjsu.cloudmanager.client.ui.model.ComputingMachineBean;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * grid panel used show cloud resource details
 * User: ckempaiah
 * Date: 10/2/11
 * Time: 9:47 PM
 * To change this template use File | Settings | File Templates.
 */
public class LabResourceMainPanel extends LayoutContainer {

    private ListStore<ModelData> gridStore;
    private LabResourceFormPanel labResourceFormPanel;
    private Grid machineGrid;

    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);
        ContentPanel cp = new ContentPanel();
        //cp.setBorders(true);
        //cp.setStyleAttribute("margin", "0px 0px 5px 0");
        //setStyleAttribute("margin", "10px");

        cp.setFrame(true);
        cp.setHeight(650);
        cp.setHeaderVisible(false);
        cp.setLayout(new RowLayout(Style.Orientation.VERTICAL));

        List<ColumnConfig> configs = new ArrayList<ColumnConfig>();

        CheckBoxSelectionModel<ModelData> checkBoxSelectionModel = new CheckBoxSelectionModel<ModelData>();

        configs.addAll(Arrays.asList(new ColumnConfig[]{
                checkBoxSelectionModel.getColumn(),
                new ColumnConfig("machineId", "", 100),
                new ColumnConfig("machineName", "Resource Name", 150),
                new ColumnConfig("machineCloudId", "Cloud Name", 100),
                new ColumnConfig("operatingSystem", "OS", 150),
                new ColumnConfig("labName", "Lab Name", 150),
                new ColumnConfig("memory", "Memory", 100)

        }));
        configs.get(1).setHidden(true);
        BaseListLoader<BaseListLoadResult<ModelData>> loader = getLoader();
        ListStore<ModelData> store = new ListStore<ModelData>(loader);
        store.setMonitorChanges(true);
        //store.add(getLabInfo());
        gridStore = store;
        ColumnModel cm = new ColumnModel(configs);

        Grid<ModelData> grid = new Grid<ModelData>(store, cm);
        grid.getView().setEmptyText("Empty");
        grid.setBorders(false);
        //grid.setAutoExpandColumn("labName");
        grid.setSelectionModel(checkBoxSelectionModel);
        //grid.addPlugin(checkBoxSelectionModel);
        this.machineGrid = grid;
        cp.add(grid, new RowData(1, 0.5));

        //cp.add(lrp, new RowData(.5, .5));
        ToolBar toolBar = new ToolBar();
        toolBar.setBorders(false);

        final LabResourceDetailPanel labResourceDetailPanel = new LabResourceDetailPanel();
        RowData rowData = new RowData(1, 0.5);
        //rowData.setMargins(new Margins(5, 0, 0, 0));

        cp.add(labResourceDetailPanel, rowData);

        toolBar.setAlignment(Style.HorizontalAlignment.LEFT);
        toolBar.add(new Button("Add", new SelectionListener<ButtonEvent>() {
            public void componentSelected(ButtonEvent ce) {
                if (labResourceFormPanel == null) {

                    labResourceFormPanel = new LabResourceFormPanel();
                }
                labResourceFormPanel.show();
                labResourceFormPanel.getFormBinding().clear();
                labResourceFormPanel.getFormBinding().bind(new ComputingMachineBean());
                //labResourceFormPanel.fireEvent(LabManagerEvents.AddMachine, baseEvent);
            }
        }));

        grid.getSelectionModel().addSelectionChangedListener(new SelectionChangedListener<ModelData>() {
            @Override
            public void selectionChanged(SelectionChangedEvent<ModelData> modelDataSelectionChangedEvent) {

                final CloudLabServiceAsync service = (CloudLabServiceAsync) Registry.get(CloudManager.CLOUD_LAB_SERVICE);
                if (modelDataSelectionChangedEvent.getSelectedItem() != null){
                    Integer machineId = ((ComputingMachineBean) modelDataSelectionChangedEvent.getSelectedItem()).getMachineId();
                    service.getComputingMachineDescription(machineId, new AsyncCallback<ComputingMachineBean>() {
                        @Override
                        public void onFailure(Throwable throwable) {
                            MessageBox.alert(MessageBox.ERROR, "Failed to get machine details", null);
                        }

                        @Override
                        public void onSuccess(ComputingMachineBean computingMachineBean) {
                            labResourceDetailPanel.getFormBinding().bind(computingMachineBean);
                        }
                    });
                }

            }
        });
        ToolbarAction.getInstance().addListener(LabManagerEvents.SaveMachine, new Listener<BaseEvent>() {
            @Override
            public void handleEvent(BaseEvent be) {
                gridStore.getLoader().load();
            }
        });
        toolBar.add(getEditButton());

        toolBar.add(getDeployButton());
        toolBar.add(getStopButton());

        toolBar.add(getDeleteButton());
        cp.setTopComponent(toolBar);
        add(cp);

        grid.addListener(Events.Render, new Listener<GridEvent<ModelData>>() {
            @Override
            public void handleEvent(GridEvent<ModelData> modelDataGridEvent) {
                gridStore.getLoader().load();
                //To change body of implemented methods use File | Settings | File Templates.
            }
        });
        setLayout(new FitLayout());
    }

    private Button getEditButton() {
        Button button = new Button("Edit", new SelectionListener<ButtonEvent>() {
            public void componentSelected(ButtonEvent ce) {
                if (labResourceFormPanel == null) {

                    labResourceFormPanel = new LabResourceFormPanel();
                }
                labResourceFormPanel.show();
                if (machineGrid.getSelectionModel().getSelectedItem() != null) {
                    if (machineGrid.getSelectionModel().getSelectedItems().size() > 1) {
                        MessageBox.alert(MessageBox.INFO, "Please select single item", null);
                    } else {
                        final CloudLabServiceAsync service = (CloudLabServiceAsync) Registry.get(CloudManager.CLOUD_LAB_SERVICE);
                        Integer machineId = ((ComputingMachineBean) machineGrid.getSelectionModel().getSelectedItem()).getMachineId();
                        service.getComputingMachineBean(machineId, new AsyncCallback<ComputingMachineBean>() {
                            @Override
                            public void onFailure(Throwable throwable) {
                                MessageBox.alert(MessageBox.ERROR, "Failed To Save ", null);
                            }

                            @Override
                            public void onSuccess(ComputingMachineBean computingMachineBean) {
                                labResourceFormPanel.getFormBinding().bind(computingMachineBean);
                            }
                        });
                    }
                }
            }
        });
        return button;
    }


    private Button getDeleteButton() {

        Button button = new Button("Delete", new SelectionListener<ButtonEvent>() {
            public void componentSelected(ButtonEvent ce) {
                if (machineGrid.getSelectionModel().getSelectedItems() != null && machineGrid.getSelectionModel().getSelectedItems().size() > 0) {
                    final CloudLabServiceAsync service = (CloudLabServiceAsync) Registry.get(CloudManager.CLOUD_LAB_SERVICE);

                    List<ComputingMachineBean> selectedItems = machineGrid.getSelectionModel().getSelectedItems();
                    if (selectedItems != null && selectedItems.size() > 0) {
                        service.terminateCloudResource(selectedItems, new AsyncCallback<Void>() {
                            @Override
                            public void onFailure(Throwable throwable) {
                                MessageBox.alert(MessageBox.ERROR, "Failed to Delete instances", null);
                            }

                            @Override
                            public void onSuccess(Void aVoid) {
                                MessageBox.alert(MessageBox.INFO, "Successfully Deleted instances", null);
                            }
                        });
                    }
                }
            }
        });
        return button;
    }

    private Button getDeployButton() {
        Button button = new Button("Deploy", new SelectionListener<ButtonEvent>() {
            public void componentSelected(ButtonEvent ce) {
                if (machineGrid.getSelectionModel().getSelectedItems() != null && machineGrid.getSelectionModel().getSelectedItems().size() > 0) {
                    final CloudLabServiceAsync service = (CloudLabServiceAsync) Registry.get(CloudManager.CLOUD_LAB_SERVICE);

                    List<ComputingMachineBean> selectedItems = machineGrid.getSelectionModel().getSelectedItems();
                    if (selectedItems != null && selectedItems.size() > 0) {
                        service.startCloudResource(selectedItems, new AsyncCallback<Void>() {
                            @Override
                            public void onFailure(Throwable throwable) {
                                MessageBox.alert(MessageBox.ERROR, "Failed to create instances", null);
                            }

                            @Override
                            public void onSuccess(Void aVoid) {
                                MessageBox.alert(MessageBox.INFO, "Successfully created instances", null);
                            }
                        });
                    }
                }
            }
        });
        return button;
    }

    private Button getStopButton() {
        Button stopButton = new Button("Stop", new SelectionListener<ButtonEvent>() {
            public void componentSelected(ButtonEvent ce) {
                if (machineGrid.getSelectionModel().getSelectedItems() != null && machineGrid.getSelectionModel().getSelectedItems().size() > 0) {
                    final CloudLabServiceAsync service = (CloudLabServiceAsync) Registry.get(CloudManager.CLOUD_LAB_SERVICE);

                    List<ComputingMachineBean> selectedItems = machineGrid.getSelectionModel().getSelectedItems();
                    if (selectedItems != null && selectedItems.size() > 0) {
                        service.stopCloudResource(selectedItems, new AsyncCallback<Void>() {
                            @Override
                            public void onFailure(Throwable throwable) {
                                MessageBox.alert(MessageBox.ERROR, "Failed to stop instances", null);
                            }

                            @Override
                            public void onSuccess(Void aVoid) {
                                MessageBox.alert(MessageBox.INFO, "Successfully stopped instances", null);

                            }
                        });
                    }
                }
            }
        });
        return stopButton;
    }

    public ListStore<ModelData> getGridStore() {
        return gridStore;
    }

    private BaseListLoader<BaseListLoadResult<ModelData>> getLoader() {
        final CloudLabServiceAsync service = (CloudLabServiceAsync) Registry.get(CloudManager.CLOUD_LAB_SERVICE);

        RpcProxy<List<com.sjsu.cloudmanager.client.ui.model.ComputingMachineBean>> proxy = new RpcProxy<List<com.sjsu.cloudmanager.client.ui.model.ComputingMachineBean>>() {
            @Override
            public void load(Object loadConfig,
                             AsyncCallback<List<com.sjsu.cloudmanager.client.ui.model.ComputingMachineBean>> callback) {
                service.getComputingMachineBeanList(callback);
            }
        };
        final BaseListLoader<BaseListLoadResult<ModelData>> loader = new BaseListLoader<BaseListLoadResult<ModelData>>(proxy);
        return loader;
    }

}
